package com.platform.common.utils.excel;


import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import com.platform.common.utils.excel.IExcelExportConfig.RenderResult;

/**
 * Excel导出工具类，工具类完成基本流程定义
 * 
 * <p>
 * 	依赖apache poi Excel操作包
 * 	如果是WEB导出，需要依赖servlet包，如不需要，则可以删除export(HttpServletRequest request, HttpServletResponse response)方法
 * 
 *  使用说明：
 *  1、WEB中使用该工具类
 *  new ExcelExport<UserInfo>(new AbsExcelExportConfig<UserInfo>() {
			public List<String> getExcelHead() {
				return Arrays.asList(new String[]{"姓名", "年龄"});
			}
			public List<UserInfo> getData(int pageIndex) {
				// pageIndex:为第几页
				List<UserInfo> list = null; // 查询第pageIndex页的数据，默认每页100条，可以覆盖getPageSize()修改
				return list;
			}
			public RenderResult renderRow(HSSFRow row, Integer rowInd, Integer colInd, UserInfo entity) {
				// row:当前Excel文档的行，rowInd:当前Excel行号，colInd:当前Excel列号0开始，entity:当前行要渲染的数据对象
				ExcelExport.insertCell(row, colInd++, entity.getName());
				ExcelExport.insertCell(row, colInd++, entity.getAge());
				// 如果需要中断导出，则return RenderResult.EXIT;
				return RenderResult.FINISH;
			}
		}).export(request, response);
 *  
 *  2、其他项目中使用该工具类
 *  new ExcelExport<UserInfo>(new AbsExcelExportConfig<UserInfo>() {
			public List<String> getExcelHead() {
				return Arrays.asList(new String[]{"姓名", "年龄"});
			}
			public List<UserInfo> getData(int pageIndex) {
				// pageIndex:为第几页
				List<UserInfo> list = null; // 查询第pageIndex页的数据，默认每页100条，可以覆盖getPageSize()修改
				return list;
			}
			public RenderResult renderRow(HSSFRow row, Integer rowInd, Integer colInd, UserInfo entity) {
				// row:当前Excel文档的行，rowInd:当前Excel行号，colInd:当前Excel列号0开始，entity:当前行要渲染的数据对象
				ExcelExport.insertCell(row, colInd++, entity.getName());
				ExcelExport.insertCell(row, colInd++, entity.getAge());
				// 如果需要中断导出，则return RenderResult.EXIT;
				return RenderResult.FINISH;
			}
		}).export(new FileOutputStream(new File("D:\\download1.xls")));
 * </p>
 * 
 * @author wei.gao
 *
 * @param <T>
 */
public class ExcelExport<T> {
	private IExcelExportConfig<T> config;
	
	public ExcelExport(IExcelExportConfig<T> config) {
		this.config = config;
	}

	/**
	 * 导出到输出流，用户导出到文件中
	 * 
	 * @param output
	 * @throws Exception
	 */
	public void export(OutputStream output) throws Exception {
		byte[] bytes = createBody(config);
		output.write(bytes);
	}
	
	/**
	 * 导出到web请求流中
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	public void export(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		byte[] fileNameByte = ("download.xls").getBytes("GBK");
		String filename = new String(fileNameByte, "ISO8859-1");

		byte[] bytes = createBody(config);
		response.setContentType("application/x-msdownload");
		response.setContentLength(bytes.length);
		response.setHeader("Content-Disposition", "attachment;filename=" + filename);
		response.getOutputStream().write(bytes);
	}

	/**
	 * 创建Excel内容
	 * @param config
	 * @return
	 * @throws Exception
	 */
	private byte[] createBody(IExcelExportConfig<T> config) throws Exception {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		// 第一步，创建一个webbook，对应一个Excel文件
		HSSFWorkbook wb = null;
		try {
			wb = new HSSFWorkbook();
			// 第二步，在webbook中添加一个sheet,对应Excel文件中的sheet
			HSSFSheet sheet = wb.createSheet(config.getSheetName());
			// 第三步，在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制short
			HSSFRow row = sheet.createRow((int) 0);
			// 第四步，创建单元格，并设置值表头 设置表头居中
			HSSFCellStyle style = wb.createCellStyle();
			style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 创建一个居中格式

			// 设置表头
			List<String> excelHead = config.getExcelHead();;

			HSSFCell cell = null;
			// excel头
			for (int i = 0; i < excelHead.size(); i++) {
				cell = row.createCell(i);
				cell.setCellValue(excelHead.get(i));
				cell.setCellStyle(style);
			}
			
			int rowNo = 1;
			loop1:while(config.hasNext()){
				List<T> list = config.getData(config.getPageIndex());
				// 无数据
				if(list == null || list.isEmpty()){
					break;
				}
				// 遍历渲染每一行
				for (T item : list) {
					row = sheet.createRow(rowNo);
					Integer j = 0;
					RenderResult flag = config.renderRow(row, rowNo++, j, item);
					if(flag == RenderResult.EXIT){
						// 退出
						break loop1;
					}
				}
			}
			wb.write(out);
		} finally {
			if (wb != null) {
				wb.close();
			}
		}
		return out.toByteArray();
	}
	
	/**
	 * 工具，插入单元格内容
	 * @param row
	 * @param i
	 * @param object
	 */
	public static void insertCell(HSSFRow row, int i, Object object){  
        if(object==null){  
            row.createCell(i).setCellValue("");  
        }else{  
            row.createCell(i).setCellValue(object.toString());  
        }  
          
    }  
}
